package com.pai4j.pay.service;


import com.alibaba.nacos.common.utils.CollectionUtils;
import com.pai4j.common.bean.APIPageResponseBean;
import com.pai4j.common.enums.WalletTransEventEnum;
import com.pai4j.common.enums.WalletTransTypeEnum;
import com.pai4j.domain.vo.response.UserBaseResponseInfoVO;
import com.pai4j.domain.vo.response.UserWalletDetailResponseVO;
import com.pai4j.pay.repository.dao.IUserWalletDAO;
import com.pai4j.pay.repository.entity.UserWalletEntity;
import com.pai4j.rmi.user.UserServiceClient;
import jakarta.persistence.criteria.Predicate;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class PaymentService {

    @Autowired
    private IUserWalletDAO userWalletDAO;

    @Autowired
    private AccountService accountService;


    public APIPageResponseBean<UserWalletDetailResponseVO> page(Integer transType, Integer eventType, String userId,
                                                           Integer pageNo, Integer pageSize) {
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "id"));
        Specification<UserWalletEntity> specification = this.createSpecification(transType, eventType, userId);
        Page<UserWalletEntity> userWalletEntityPage = userWalletDAO.findAll(specification, pageable);

        List<UserWalletDetailResponseVO> userWalletDetailResponseVOS = new ArrayList<>();
        List<UserWalletEntity> userWalletEntities = userWalletEntityPage.getContent();
        if (CollectionUtils.isNotEmpty(userWalletEntities)) {
            userWalletDetailResponseVOS = userWalletEntities.stream().map(this::convert).collect(Collectors.toList());
            Set<String> userIdSet = userWalletEntities.stream().map(UserWalletEntity::getUserId).collect(Collectors.toSet());
            Map<String, UserBaseResponseInfoVO> userMap = accountService.batchGet(userIdSet);
            userWalletDetailResponseVOS.forEach(uw -> uw.setUser(userMap.get(uw.getUserId())));
        }
        return APIPageResponseBean.success(pageNo, pageSize, userWalletEntityPage.getTotalElements(), userWalletDetailResponseVOS);
    }

    private UserWalletDetailResponseVO convert(UserWalletEntity entity) {
        UserWalletDetailResponseVO vo = new UserWalletDetailResponseVO();
        vo.setUserId(entity.getUserId());
        vo.setEvent(entity.getTransEvent());
        vo.setType(entity.getTransType());
        vo.setMoney(entity.getMoney().toString());
        vo.setTypeName(WalletTransTypeEnum.getTransTypeName(entity.getTransType()));
        vo.setEventName(WalletTransEventEnum.getEventName(entity.getTransEvent()));
        vo.setTime(entity.getTransDate() != null ? entity.getTransDate().getTime() : null);
        return vo;
    }

    private Specification<UserWalletEntity> createSpecification(Integer transType, Integer eventType, String userId) {
        return  ((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (transType != null) {
                predicates.add(criteriaBuilder.equal(root.get("transType").as(Integer.class), transType));
            }
            if (eventType != null) {
                predicates.add(criteriaBuilder.equal(root.get("eventType").as(Integer.class), eventType));
            }
            if (StringUtils.isNotBlank(userId)) {
                predicates.add(criteriaBuilder.equal(root.get("userId").as(String.class), userId));
            }
            Predicate[] pre = new Predicate[predicates.size()];
            criteriaQuery.where(predicates.toArray(pre));
            return criteriaQuery.getRestriction();
        });
    }
}
